package com.example.factory.api.dto.assembler;

import com.example.factory.api.dto.DtoReportGarding;
import com.example.factory.api.dto.form.DtoReportGardingForm;
import com.example.factory.core.domain.*;
import com.example.factory.core.repository.Level1DimensionRepository;
import com.example.factory.core.repository.Level2DimensionRepository;
import com.example.factory.core.repository.ReportLevel2DimensionRepository;
import com.example.factory.core.repository.ReportPlanRepository;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Lei Tao
 */
@Component
public class ReportGardingAssmbler {
    private final Level1DimensionRepository level1DimensionRepository;
    private final Level2DimensionRepository level2DimensionRepository;
    private final ReportLevel2DimensionRepository reportLevel2DimensionRepository;
    private final ReportPlanRepository reportPlanRepository;

    public ReportGardingAssmbler(Level1DimensionRepository level1DimensionRepository, Level2DimensionRepository level2DimensionRepository, ReportLevel2DimensionRepository reportLevel2DimensionRepository, ReportPlanRepository reportPlanRepository) {
        this.level1DimensionRepository = level1DimensionRepository;
        this.level2DimensionRepository = level2DimensionRepository;
        this.reportLevel2DimensionRepository = reportLevel2DimensionRepository;
        this.reportPlanRepository = reportPlanRepository;
    }


    public ReportLevel1Dimension toReportLevel1Dimension(DtoReportGardingForm dtoReportGardingForm) {
        ReportLevel1Dimension reportLevel1Dimension = new ReportLevel1Dimension();
        Level1Dimension level1Dimension = level1DimensionRepository.findByGuidAndArchivedFalse(dtoReportGardingForm.getLevel1Guid());
        reportLevel1Dimension.setLevel1Dimension(level1Dimension);
        List<DtoReportGardingForm.Level2> level2s = dtoReportGardingForm.getLevel2s();
        float totalScore = 0;
        List<ReportLevel2Dimension> level2Dimensions = new ArrayList<>();
        for (DtoReportGardingForm.Level2 level2 : level2s) {
            Level2Dimension level2Dimension = level2DimensionRepository.findByGuidAndArchivedFalse(level2.getLevel2Guid());
            ReportLevel2Dimension reportLevel2Dimension = new ReportLevel2Dimension();
            reportLevel2Dimension.setLevel2Dimension(level2Dimension);
            reportLevel2Dimension.setScore(level2.getScore());
            reportLevel2DimensionRepository.save(reportLevel2Dimension);
            level2Dimensions.add(reportLevel2Dimension);
            totalScore = totalScore + level2.getScore();
        }
        reportLevel1Dimension.setReportLevel2Dimensions(level2Dimensions);
        Float weight = level1Dimension.getWeight();
        totalScore = totalScore * weight;
        reportLevel1Dimension.setTotalScore(totalScore);
        ReportPlan reportPlan = reportPlanRepository.findByGuidAndArchivedFalse(dtoReportGardingForm.getReportGuid());
        reportLevel1Dimension.setReportPlan(reportPlan);
        return reportLevel1Dimension;
    }

    public DtoReportGarding toDtoReportGarding(ReportLevel1Dimension reportLevel1Dimension) {
        DtoReportGarding dtoReportGarding = new DtoReportGarding();
        dtoReportGarding.setGuid(reportLevel1Dimension.getGuid());
        dtoReportGarding.setLevel1Guid(reportLevel1Dimension.getLevel1Dimension().getGuid());
        dtoReportGarding.setLevel1Name(reportLevel1Dimension.getLevel1Dimension().getName());
        List<DtoReportGarding.Level2> level2s = toLevel2s(reportLevel1Dimension);
        dtoReportGarding.setLevel2s(level2s);
        dtoReportGarding.setTotalScore(reportLevel1Dimension.getTotalScore());
        return dtoReportGarding;
    }

    public List<DtoReportGarding.Level2> toLevel2s(ReportLevel1Dimension reportLevel1Dimension) {
        return reportLevel1Dimension.getReportLevel2Dimensions().stream().map(level2Dimension -> {
            DtoReportGarding.Level2 level2 = new DtoReportGarding.Level2();
            level2.setLevel2Guid(level2Dimension.getGuid());
            level2.setLevel2Name(level2Dimension.getLevel2Dimension().getName());
            level2.setScore(level2Dimension.getScore());
            return level2;
        }).collect(Collectors.toList());
    }
}
